home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
FishMarket 1.0
/
FishMarket v1.0.iso
/
fishies
/
501-525
/
disk_519
/
oaklisp
/
src.lzh
/
stacks.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-06-15
|
4KB
|
154 lines
/* Copyright (C) 1987, Barak Pearlmutter & Kevin Lang. */
#include <stdio.h>
#include "emulator.h"
#include "stacks.h"
#ifndef FAST
extern bool trace_segs;
#endif
/* This routine flushes out the stack buffer, leaving amount_to_leave. */
void flush_buffer(pstk, amount_to_leave)
stack *pstk;
int amount_to_leave;
{
segment *s;
long i , count = pstk->ptr - (&pstk->data[0]-1)
, amount_to_flush = count - amount_to_leave
, amount_unflushed = amount_to_flush;
ref *src = &pstk->data[0]
, *end = pstk->ptr - amount_to_leave;
while (src < end)
{
/* Flush a single segment. */
long size = amount_unflushed;
if (size > MAX_SEGMENT_SIZE)
size = MAX_SEGMENT_SIZE;
{
ref *p;
ALLOCATE(p, size+SEGMENT_HEADER_LENGTH,
"space crunch allocating stack segment");
s = (segment *)p;
}
s->type_field = e_segment_type;
s->length_field = INT_TO_REF(size+SEGMENT_HEADER_LENGTH);
s->previous_segment = pstk->segment;
pstk->segment = PTR_TO_REF(s);
for (i=0; i<size; i++)
s->data[i] = *src++;
amount_unflushed -= size;
#ifndef FAST
if (trace_segs) printf("P");
#endif
}
for (i=0; i<amount_to_leave; i++)
pstk->data[i] = *src++;
pstk->ptr = &pstk->data[amount_to_leave-1];
pstk->pushed_count += amount_to_flush;
#ifndef FAST
if (trace_segs) printf(".");
#endif
}
/* This routine grabs some segments that have been flushed from the buffer
and puts them back in. Because the segments might be small, it
may have to put more than one segment back in. It grabs enough so that
the buffer has at least n+1 values in it, so that at least n values could
be popped off without underflow. */
void unflush_buffer(pstk, n)
stack *pstk;
int n;
{
long i
, number_to_pull = 0
, count = pstk->ptr - (&pstk->data[0]-1)
, new_count = count;
segment *s = (segment *)REF_TO_PTR(pstk->segment);
ref *dest;
/* First, figure out how many segments to pull. */
for (; new_count <= n; s = (segment *)REF_TO_PTR(s->previous_segment))
{
new_count += REF_TO_INT(s->length_field) - SEGMENT_HEADER_LENGTH;
number_to_pull += 1;
}
/* Copy the data in the buffer up to its new home. */
dest = &pstk->data[new_count - 1];
for (i = count-1; i>=0; i--)
*dest-- = pstk->data[i];
/* Suck in the segments. */
for (s = (segment *)REF_TO_PTR(pstk->segment);
number_to_pull>0; number_to_pull--)
{
/* Suck in this segment. */
for (i = REF_TO_INT(s->length_field) - SEGMENT_HEADER_LENGTH - 1
; i >= 0; i--)
*dest-- = s->data[i];
s = (segment *)REF_TO_PTR(s->previous_segment);
#ifndef FAST
if (trace_segs) printf("p");
#endif
}
pstk->segment = PTR_TO_REF(s);
pstk->ptr = &pstk->data[new_count-1];
pstk->pushed_count -= new_count - count;
#ifndef FAST
if (trace_segs) printf(".");
#endif
}
void dump_stack_proc(pstk)
stack *pstk;
{
ref *p;
(void)printf("stack contents (%d): ", stk_height(*pstk));
/* For now, we don't bother to print the segments. */
for (p = &pstk->data[0]; p<=pstk->ptr; p++)
{
printref(*p);
(void)putc(p == pstk->ptr ? '\n' : ' ', stdout);
}
fflush_stdout();
}
void init_stk(pstk)
stack *pstk;
{
#ifdef MALLOC_STACK_BUFFER
pstk->data = (ref *)my_malloc((long)(sizeof(ref) * STACK_BUFFER_SIZE));
#endif
pstk->ptr = &pstk->data[0];
pstk->data[0] = INT_TO_REF(1234);
/* This becomes e_nil when segment_type is loaded. */
pstk->segment = INT_TO_REF(0);
pstk->pushed_count = 0;
}